import WebSocketEvent from '@/event/webSocketEvent'
import { useUserStoreHook } from '@/stores/modules/user'
import NoticeEvents from '@/event/noticeEvents'

/**
 * 获取 WebSocket 地址
 */
function getWebSocketUrl() {
  return `${import.meta.env.VITE_WS_URL}/ws/${getToken()}`
}

/**
 * 获取 Token
 */
function getToken() {
  return useUserStoreHook().accessToken
}

/**
 * WebSocket
 */
class WebSocketUtils {
  /** 是否已连接 */
  private connected: boolean = false
  /** 心跳定时器 */
  private heartbeatTimer: ReturnType<typeof setInterval> | null
  /** 重连定时器 */
  private reconnectionTimer: ReturnType<typeof setInterval> | null = null
  /** 重连次数 */
  private reconnectionAttempts: number = 10
  /** 是否需要重连 */
  private isReconnect: boolean = true
  /** 当前重连次数 */
  private currentReconnectionAttempts: number = 1
  /** 重连间隔 */
  private reconnectInterval = 5000
  /** 心跳间隔 */
  private heartbeatInterval = 5000
  // 实例
  private webSocket: WebSocket | null = null

  constructor() {
    this.heartbeatTimer = null
    this.reconnectionTimer = null
  }

  /**
   * 连接
   */
  connect() {
    this.webSocket = new WebSocket(getWebSocketUrl())
    // 监听连接打开
    this.webSocket.onopen = (e) => {
      this.onWebSocketOpen(e)
    }
    // 监听消息
    this.webSocket.onmessage = (e) => {
      this.onWebSocketMessage(e)
    }
    this.webSocket.onerror = (e) => {
      console.log('WebSocket连接失败', e)
    }
    // 监听关闭
    this.webSocket.onclose = () => {
      this.connected = false
      // 清除心跳定时器
      clearInterval(this.heartbeatTimer as any)
      clearInterval(this.reconnectionTimer as any)
      console.log(`WebSocket连接失败,执行第${this.currentReconnectionAttempts}次重连...`)
      if (this.currentReconnectionAttempts > this.reconnectionAttempts) {
        console.log('重连次数达到上限，停止重连')
        return
      }
      if (this.isReconnect) {
        // 执行重连
        this.startReconnect()
      }
    }
    console.log('WebSocket连接中...')
  }

  /**
   * 监听消息
   * @param event
   */
  onWebSocketMessage(event: MessageEvent) {
    console.log('WebSocket收到消息', event.data)
    const data = JSON.parse(event.data)
    // 系统消息
    if (data.type.includes('system')) {
      NoticeEvents.emit('on:system:message', data)
    }
    if (event.data == 'TOKEN_INVALID') {
      // token无效
      WebSocketEvent.emit('on:tokenInvalid', null)
    }
    // 其他消息
    else {
      WebSocketEvent.emit('on:message', event.data)
    }
  }

  /**
   * 监听连接打开
   * @param event
   */
  onWebSocketOpen(event: Event) {
    console.log('WebSocket连接打开')
    this.isReconnect = true
    this.connected = true
    this.resetReconnect()
    // 发送心跳
    this.heartbeat()
  }

  /**
   * 重置重连
   * @private
   */
  resetReconnect() {
    this.reconnectionAttempts = 10
    this.currentReconnectionAttempts = 1
    // 清除重连定时器
    clearInterval(this.reconnectionTimer as any)
  }

  /**
   * 发送消息纯文本
   * @param message
   */
  public sendText(message: string) {
    if (!this.connected) return
    this.webSocket?.send(message)
  }

  /**
   * 发送消息JSON
   * @param message
   */
  public sendJson(message: object) {
    if (!this.connected) return
    this.webSocket?.send(JSON.stringify(message))
  }

  /**
   * 重连
   * @private
   */
  startReconnect() {
    // 重连次数
    if (this.currentReconnectionAttempts > this.reconnectionAttempts) return
    // // 如果已经连接，则不需要重连
    if (this.connected) {
      return
    }
    this.reconnectionTimer = setInterval(() => {
      this.currentReconnectionAttempts++
      this.connect()
    }, this.reconnectInterval)
  }

  /**
   * 心跳
   * @private
   */
  private heartbeat() {
    if (!this.connected) return
    console.log('开启WebSocket心跳')
    let that = this
    this.heartbeatTimer = setInterval(() => {
      that.sendText('ping')
    }, this.heartbeatInterval)
  }
}

export default new WebSocketUtils()
